package com.iot.ic.tcp.utils;


import java.nio.charset.Charset;
import java.util.*;

/**
 * byte与其他数组相互转换的工具类
 *
 * @author xiuge
 *         2016年10月14日上午11:19:44
 */
public class ByteUtil {

    /**
     * byte类型的十六进制数转换成字符串(HexString——>byte)
     *
     * @param src
     * @return
     */
    public static String[] bytesToHexStrings(byte[] src) {
        if (src == null || src.length <= 0) {
            return null;
        }
        String[] str = new String[src.length];
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                str[i] = "0" + hv;
            } else {
                str[i] = hv;
            }
        }
        return str;
    }

    /**
     * 设备编号转换为字节链
     * @param deviceNo
     * @return
     */
    public static List<Byte> getBytesbyDeviceNo(String deviceNo){
        int len = (deviceNo.length() / 2);
        List<Byte> result = new ArrayList<Byte>();
        char[] achar = deviceNo.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            byte byteTmp = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
            result.add(byteTmp);
        }
        return result;
    }

    private static int toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * 字节转换为对应的十六进制字符串
     * @param data
     * @return
     */
    public static String byteToHexString(Byte data){
        String result="";
        int v = data & 0xFF;
        String hv = Integer.toHexString(v);
        if (hv.length() < 2) {
            result = "0" + hv;
        } else {
            result = hv;
        }
        return  result;
    }

    /**
     * HexString——>byte
     *
     * @param hexString
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    /**
     * byte——>String
     *
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }


    /**
     * short->byte数组,   ( 0X0102->{1,2} )
     *
     * @param data
     * @return
     */
    public static Byte[] getBytes(short data) {
        Byte[] bytes = new Byte[2];
        bytes[1] = (byte) (data & 0xff);
        bytes[0] = (byte) ((data & 0xff00) >> 8);
        return bytes;
    }
    
    public static byte[] getbytes(short data) {
    	byte[] bytes = new byte[2];
        bytes[1] = (byte) (data & 0xff);
        bytes[0] = (byte) ((data & 0xff00) >> 8);
        return bytes;
    }

    /**
     * char->byte数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(char data) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (data);
        bytes[1] = (byte) (data >> 8);
        return bytes;
    }

    /**
     * int->byte数组
     *
     * @param data
     * @return
     */
    public static Byte[] getBytes(int data) {
        Byte[] bytes = new Byte[4];
        bytes[3] = (byte) (data & 0xff);
        bytes[2] = (byte) ((data & 0xff00) >> 8);
        bytes[1] = (byte) ((data & 0xff0000) >> 16);
        bytes[0] = (byte) ((data & 0xff000000) >> 24);
        return bytes;
    }

    /**
     * long->byte数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(long data) {
        byte[] bytes = new byte[8];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data >> 8) & 0xff);
        bytes[2] = (byte) ((data >> 16) & 0xff);
        bytes[3] = (byte) ((data >> 24) & 0xff);
        bytes[4] = (byte) ((data >> 32) & 0xff);
        bytes[5] = (byte) ((data >> 40) & 0xff);
        bytes[6] = (byte) ((data >> 48) & 0xff);
        bytes[7] = (byte) ((data >> 56) & 0xff);
        return bytes;
    }

    /**
     * byte->byte数组
     *
     * @param data
     * @return
     */
    public static Byte[] getBytes(float data) {
        int intBits = Float.floatToIntBits(data);
        Byte[] bytes = getBytes(intBits);
        return bytes;
    }

    /**
     * double->byte数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(double data) {
        long intBits = Double.doubleToLongBits(data);
        return getBytes(intBits);
    }


    /**
     * 字符串转byte数组
     *
     * @param data
     * @param charsetName 字符集
     * @return
     */
    public static byte[] getBytes(String data, String charsetName) {
        Charset charset = Charset.forName(charsetName);
        return data.getBytes(charset);
    }

    /**
     * 字符串转byte数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(String data) {
        return getBytes(data, "GBK");
    }
    
    /**
     * 字符串转byte数组
     *
     * @param data
     * @return
     */
    public static byte[] getUtf8Bytes(String data) {
        return getBytes(data, "utf-8");
    }

    /**
     * byte数组转short
     *
     * @param bytes
     * @return
     */
    public static short getShort(Byte[] bytes) {
        return (short) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
    }

    /**
     * byte数组转short
     *
     * @param bytes
     * @return
     */
    public static short getShort(byte[] bytes) {
        return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
    }

    /**
     * byte数组转char
     *
     * @param bytes
     * @return
     */
    public static char getChar(byte[] bytes) {
        return (char) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
    }

    /**
     * byte数组转int
     *
     * @param bytes
     * @return
     */
    public static int getInt(byte[] bytes) {
        return (0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)) | (0xff0000 & (bytes[2] << 16))
                | (0xff000000 & (bytes[3] << 24));
    }

    /**
     * byte数组转Long
     *
     * @param bytes
     * @return
     */
    public static long getLong(byte[] bytes) {
        return (0xffL & (long) bytes[0]) | (0xff00L & ((long) bytes[1] << 8)) | (0xff0000L & ((long) bytes[2] << 16))
                | (0xff000000L & ((long) bytes[3] << 24)) | (0xff00000000L & ((long) bytes[4] << 32))
                | (0xff0000000000L & ((long) bytes[5] << 40)) | (0xff000000000000L & ((long) bytes[6] << 48))
                | (0xff00000000000000L & ((long) bytes[7] << 56));
    }

    /**
     * byte数组转float
     *
     * @param bytes
     * @return
     */
    public static float getFloat(Byte[] bytes) {
        byte[] result = new byte[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            result[i] = bytes[3 - i];
        }
        return Float.intBitsToFloat(getInt(result));
    }

    /**
     * byte数组转double
     *
     * @param bytes
     * @return
     */
    public static double getDouble(byte[] bytes) {
        long l = getLong(bytes);
        System.out.println(l);
        return Double.longBitsToDouble(l);
    }

    /**
     * byte数组转String
     *
     * @param bytes
     * @param charsetName 字符集
     * @return
     */
    public static String getString(byte[] bytes, String charsetName) {
        return new String(bytes, Charset.forName(charsetName));
    }

    /**
     * byte数组转String
     *
     * @param bytes
     * @return
     */
    public static String getString(byte[] bytes) {
        return getString(bytes, "GBK");
    }


    /**
     * 读取六个字节组成的Mac
     *
     * @param start
     * @param message
     * @return
     */
    public static String readMac(int start, byte[] message) {
        byte[] macArr = Arrays.copyOfRange(message, start, start + 6);
        String[] macStrs = ByteUtil.bytesToHexStrings(macArr);
        String mac = macStrs[0] + macStrs[1] + macStrs[2] + macStrs[3] + macStrs[4] + macStrs[5];// mac地址
        mac = mac.toUpperCase();
        return mac;
    }

    /**
     * 读取时间
     *
     * @param data
     * @return
     */
    public static Date readTime(Byte[] data) {
        int year = data[0] + 2000;
        int month = data[1] - 1;
        int day = data[2];
        int hour = data[3];
        int min = data[4];
        int sec = data[5];
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day, hour, min, sec);
        long millis = calendar.getTimeInMillis() / 1000 * 1000;//毫秒取零
        calendar.setTimeInMillis(millis);
        Date date = calendar.getTime();
        return date;
    }

    /**
     * 读取时间
     * @param dateList
     * @return
     */
    public static Date getTime(List<Byte> dateList){
        int year = dateList.get(0) + 2000;
        int month = dateList.get(1) - 1;
        int day = dateList.get(2);
        int hour = dateList.get(3);
        int min = dateList.get(4);
        int sec = dateList.get(5);
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day, hour, min, sec);
        long millis = calendar.getTimeInMillis() / 1000 * 1000;//毫秒取零
        calendar.setTimeInMillis(millis);
        Date date = calendar.getTime();
        return date;
    }

    /**
     * 获取温度
     * @param temList
     * @return
     */
    public static Float getTem(List<Byte> temList){
        int intNum=temList.get(1);
        int decimalNum=temList.get(2);
        Float num=intNum+0.1f*decimalNum;
        if (temList.get(0)==null||temList.get(0)==2)
            return null;
        if (temList.get(0)==1)
            num=num*-1;
        return num;
    }

    /**
     * 获取湿度
     * @param humList
     * @return
     */
    public static Integer getHum(List<Byte> humList){
        int intNum=humList.get(1);
        if (humList.get(0)==null||humList.get(0)==2)
            return null;
        return intNum;
    }

    /**
     * 获取温度字节数组
     * @param tem
     * @return
     */
    public static List<Byte> getTemBytes(float tem){
        List<Byte>temList=new ArrayList<>();
        temList.add(tem>0?(byte)0:(byte)1);
        temList.add((byte)tem);
        temList.add((byte) (tem*10%10));
        return temList;
    }

    /**
     * 获取湿度字节数组
     * @param hum
     * @return
     */
    public static List<Byte> getHumBytes(int hum){
        List<Byte>humList=new ArrayList<>();
        humList.add(hum>0?(byte)0:(byte)1);
        humList.add((byte)hum);
        return humList;
    }


    /**
     * 读取故障数据
     *
     * @param data
     * @return
     */
    public static int readFault(List<Byte> data) {
        short upData = data.get(0);
        short lowData = data.get(1);
        int fault = upData << 8 + lowData;
        return fault;
    }

    /**
     * 读取ip和端口字符串
     *
     * @param data
     * @return
     */
    public static String readIpAndPort(Byte[] data) {
        Byte[] ipBytes = Arrays.copyOfRange(data, 0, 4);
        String ipStr = "";
        for (int i = 0; i < ipBytes.length; i++) {
            short part = ipBytes[i];
            if (i != 0) {
                ipStr += "." + part;
            } else {
                ipStr += part;
            }
        }
        Byte[] portBytes = Arrays.copyOfRange(data, 4, 6);
        short port = getShort(portBytes);
        return ipStr + ":" + port;
    }

    /**
     * 时间转Byte数组
     *
     * @param date
     * @return
     */
    public static Byte[] getBytes(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        Byte year = (byte) (calendar.get(Calendar.YEAR) - 2000);
        Byte month = (byte) (calendar.get(Calendar.MONTH) + 1);
        Byte day = (byte) calendar.get(Calendar.DAY_OF_MONTH);
        Byte hour = (byte) calendar.get(Calendar.HOUR_OF_DAY);
        Byte minite = (byte) calendar.get(Calendar.MINUTE);
        Byte second = (byte) calendar.get(Calendar.SECOND);
        Byte[] bytes = new Byte[]{year, month, day, hour, minite, second};
        return bytes;
    }

    /**
     * ip和端口转换为字节数组
     *
     * @param port
     * @return
     */
    public static Byte[] getBytes(String ip, int port) {
        Byte[] bytes = new Byte[6];
        String[] ipStrings = ip.split("\\.");
        for (int i = 0; i < ipStrings.length; i++) {
            short part = Short.valueOf(ipStrings[i]);
            bytes[i] = (byte) part;
        }
        Byte[] portPart = getBytes((short) port);
        System.arraycopy(portPart, 0, bytes, 4, 2);
        return bytes;
    }

    /**
     * ip和端口转换为字节数组
     *
     * @param ipPort
     * @return
     */
    public static Byte[] getBytesByIpPort(String ipPort) {
        String[] ipPortArr = ipPort.split(":");
        Byte[] bytes = new Byte[6];
        String[] ipStrings = ipPortArr[0].split("\\.");
        for (int i = 0; i < ipStrings.length; i++) {
            short part = Short.valueOf(ipStrings[i]);
            bytes[i] = (byte) part;
        }
        Byte[] portPart = getBytes(Short.valueOf(ipPortArr[1]));
        System.arraycopy(portPart, 0, bytes, 4, 2);
        return bytes;
    }

    /**
     * 把字节数组转为十六进制表示的字符串
     *
     * @param bytes
     * @return
     */
    public static String[] getHexString(byte[] bytes) {
        String[] hexStrs = new String[bytes.length];
        for (int i = 0; i < hexStrs.length; i++) {
            int tem = (int) (bytes[i] & 0xff);
            hexStrs[i] = Integer.toHexString(tem);
            if (hexStrs[i].length() == 1) {
                hexStrs[i] = "0" + hexStrs[i];
            }
        }
        return hexStrs;
    }
    
    /**
     * 把字节数组转为十六进制表示的字符串
     *
     * @param bytes
     * @return
     */
    public static String[] getHexString(Byte[] bytes) {
        String[] hexStrs = new String[bytes.length];
        for (int i = 0; i < hexStrs.length; i++) {
            int tem = (int) (bytes[i] & 0xff);
            hexStrs[i] = Integer.toHexString(tem);
            if (hexStrs[i].length() == 1) {
                hexStrs[i] = "0" + hexStrs[i];
            }
        }
        return hexStrs;
    }

    /**
     * byte链转十六进制字符串
     * @param noList
     * @return
     */
    public static String getNoByList(List<Byte> noList){
        String mac="";
        for (Byte byteStr:noList){
            String hex = byteToHexString(byteStr);
            mac+=hex;
        }
        mac = mac.toUpperCase();
        return mac;
    }
 
    
    public static byte[] subBytes(byte[] src, int begin, int count) {  
        byte[] bs = new byte[count];  
        System.arraycopy(src, begin, bs, 0, count);  
        return bs;  
    }
    
    public static byte[] subBytes(Byte[] src, int begin, int count) {  
        byte[] bs = new byte[count];  
        System.arraycopy(src, begin, bs, 0, count);  
        return bs;  
    }
    
    /**
	* <p>Title: connect</p>
	* <p>Description: 连接多个字节</p>
	* @author Wei.Guo
	* @param head
	* @param body
	* @return
	*/
	public static byte[] connect(byte[] head,byte...body){
		byte[] message=new byte[head.length+body.length];
        for (int i = 0; i < head.length; i++) {
	    	 message[i]=head[i];
		}
        for (int i=head.length; i < message.length;i++){
	    	 message[i]=body[i-head.length];
        }
        return message;
	}
	
	
	 /** 
     * 将long数值转换为占四个字节的byte数组，本方法适用于(高位在前，低位在后)的顺序。  和bytesToInt2（）配套使用
     * @param value 
     *            要转换的long值
     */
	public static byte[] toBytes2(long value) {
		byte[] src = new byte[4]; 
		src[3] = (byte) (value & 0xFF);
		src[2] = (byte) ((value>>8)&0xFF);
		src[1] = (byte) ((value>>16)& 0xFF);
		src[0] = (byte) ((value>>24) & 0xFF);
		return src;
	}
	
	public static long byteToLong2(byte[] src,int offset) {

		long value = (int) ( ((src[offset] & 0xFF)<<24)
				|((src[offset+1] & 0xFF)<<16)
				|((src[offset+2] & 0xFF)<<8)
				|(src[offset+3] & 0xFF));
		return value;
	}
	
	public static byte[] sort(byte[] array){
		int len = array.length;
		byte[] newArray = new byte[len];
		for(int i=0;i < len; i++){
	    newArray[i] = array[len-1-i];
		}
		return newArray;
	}
	
	public static byte[] byteAddZero(byte[] array, int len){
		int arrayLen = array.length;
		int zeroLengh = len - arrayLen;
		byte[] newArray = new byte[len];
		byte[] zeroArray = new byte[zeroLengh];	
		for(int i=0;i < zeroLengh; i++){
			zeroArray[i] = 0x00;
		}
		newArray = connect(array,zeroArray);
		return newArray;
	}
	
	
	public static byte[] timeToBytesJcj(long time){
		byte[] timebytes = ByteUtil.toBytes2(time);
		timebytes = ByteUtil.sort(timebytes);
		return timebytes;
	}

    /**
     * byte数组转字符串
     * @param recv
     * @return
     */
    public static String getJsonStringByBytes(byte[] recv){
        char [] jsonChars=new char[recv.length];
        for (int i=0;i<recv.length;i++) {
            jsonChars[i]=(char) recv[i];
        }
        String jsonStr=new String(jsonChars);
        return jsonStr;
    }

}
